#ifndef NET_CHANNEL_H
#define NET_CHANNEL_H

#include <functional>
#include <memory>

namespace net {

class EventLoop;

/**
 * @class Channel
 * @brief 封装文件描述符和其感兴趣的I/O事件，以及回调函数
 * @details Channel类是Reactor模式中的事件处理器，
 *          每个Channel对象对应一个文件描述符，
 *          负责注册、处理该fd上的I/O事件
 */
class Channel
{
public:
    using EventCallback = std::function<void()>;    // 事件回调函数类型

    /**
     * @brief 构造函数
     * @param loop 所属的EventLoop
     * @param fd 关联的文件描述符
     */
    Channel(EventLoop* loop, int fd);

    /**
     * @brief 析构函数
     */
    ~Channel();
    
    /**
     * @brief 设置读事件回调函数
     * @param cb 回调函数对象
     */
    void setReadCallback(EventCallback cb)
    { _readCallback = std::move(cb); }
    
    /**
     * @brief 设置写事件回调函数
     * @param cb 回调函数对象
     */
    void setWriteCallback(EventCallback cb)
    { _writeCallback = std::move(cb); }
    
    /**
     * @brief 设置关闭事件回调函数
     * @param cb 回调函数对象
     */
    void setCloseCallback(EventCallback cb)
    { _closeCallback = std::move(cb); }
    
    /**
     * @brief 设置错误事件回调函数
     * @param cb 回调函数对象
     */
    void setErrorCallback(EventCallback cb)
    { _errorCallback = std::move(cb); }

    /**
     * @brief 设置通用事件回调函数(所有事件都会调用)
     * @param cb 回调函数对象
     */
    void setEventCallback(EventCallback cb)
    { _eventCallback = std::move(cb); }
    
    /**
     * @brief 绑定对象，防止在处理事件时对象被销毁
     * @param tie 绑定的对象
     */
    void tie(const std::shared_ptr<void>&);
    
    /**
     * @brief 获取文件描述符
     * @return 文件描述符
     */
    int fd() const { return _fd; }

    /**
     * @brief 获取关注的事件
     * @return 事件掩码
     */
    int events() const { return _events; }

    /**
     * @brief 设置就绪事件(由EventLoop/Poller调用)
     * @param revt 就绪事件掩码
     */
    void setRevents(int revt) { _revents = revt; }
    
    /**
     * @brief 启用读事件
     * @details 注册EPOLLIN和EPOLLPRI事件，更新到Poller
     */
    void enableReading() { _events |= kReadEvent; update(); }

    /**
     * @brief 禁用读事件
     * @details 从关注事件中移除EPOLLIN和EPOLLPRI，更新到Poller
     */
    void disableReading() { _events &= ~kReadEvent; update(); }

    /**
     * @brief 启用写事件
     * @details 注册EPOLLOUT事件，更新到Poller
     */
    void enableWriting() { _events |= kWriteEvent; update(); }

    /**
     * @brief 禁用写事件
     * @details 从关注事件中移除EPOLLOUT，更新到Poller
     */
    void disableWriting() { _events &= ~kWriteEvent; update(); }

    /**
     * @brief 禁用所有事件
     * @details 清空所有关注的事件，更新到Poller
     */
    void disableAll() { _events = kNoneEvent; update(); }

    /**
     * @brief 判断是否启用了写事件
     * @return 如果启用了写事件返回true，否则返回false
     */
    bool isWriting() const { return _events & kWriteEvent; }

    /**
     * @brief 判断是否启用了读事件
     * @return 如果启用了读事件返回true，否则返回false
     */
    bool isReading() const { return _events & kReadEvent; }

    /**
     * @brief 判断是否没有关注任何事件
     * @return 如果没有关注事件返回true，否则返回false
     */
    bool isNoneEvent() const { return _events == kNoneEvent; }

    /**
     * @brief 处理事件
     * @details 根据poller返回的就绪事件，调用相应的回调函数
     */
    void handleEvent();
    
    /**
     * @brief 从EventLoop中移除该Channel
     */
    void remove();

private:
    /**
     * @brief 更新Channel在Poller中的状态
     * @details 调用EventLoop的updateChannel方法
     */
    void update();

    /**
     * @brief 安全调用事件处理
     */
    void handleEventWithGuard();

    // 事件常量定义
    static const int kNoneEvent;    // 无事件
    static const int kReadEvent;    // 读事件(EPOLLIN | EPOLLPRI)
    static const int kWriteEvent;   // 写事件(EPOLLOUT)

    EventLoop* _loop;   // 所属EventLoop
    const int _fd;      // 文件描述符
    int _events;        // 关注的事件
    int _revents;       // 目前活动的事件

    EventCallback _readCallback;        // 读事件回调
    EventCallback _writeCallback;       // 写事件回调
    EventCallback _closeCallback;       // 关闭事件回调
    EventCallback _errorCallback;       // 错误事件回调
    EventCallback _eventCallback;       // 通用事件回调

    bool _tied = false;
    std::weak_ptr<void> _tie;
};

} // namespace net

#endif // NET_CHANNEL_H